with GWindows;
with GWindows.GStrings;
with GWindows.Common_Dialogs;

--with Constants.Resources;

with export;
with time;   use time;

package body GUI.Log is
  procedure Filter (Window : in out Log_Window_Type; i : in integer) is
    procedure Filter_by_Type (i : in integer) is
      procedure Insert_Item is
        pos : constant Integer := Item_Count(Window.Filtered_Log);
      begin
        Insert_Item(Window.Filtered_Log, Text(Window.Log, i, 0), pos);
        Set_Sub_Item(Window.Filtered_Log, Text(Window.Log, i, 1), pos, 1);
        Set_Sub_Item(Window.Filtered_Log, Text(Window.Log, i, 2), pos, 2);
        Set_Sub_Item(Window.Filtered_Log, Text(Window.Log, i, 3), pos, 3);
      end Insert_Item;
    begin
      if to_boolean(State(Window.Tell_Chk))
        and Text(Window.Log, i, 2) = GUI_Strings.Tell
      then
        Insert_Item;
      elsif to_boolean(State(Window.LS_Chk))
        and Text(Window.Log, i, 2) = GUI_Strings.Linkshell
      then
        Insert_Item;
      elsif to_boolean(State(Window.Party_Chk))
        and Text(Window.Log, i, 2) = GUI_Strings.Party
      then
        Insert_Item;
      elsif to_boolean(State(Window.Say_Chk))
        and Text(Window.Log, i, 2) = GUI_Strings.Say
      then
        Insert_Item;
      elsif to_boolean(State(Window.Shout_Chk))
        and Text(Window.Log, i, 2) = GUI_Strings.Shout
      then
        Insert_Item;
      elsif to_boolean(State(Window.Other_Chk))
        and (Text(Window.Log, i, 2) = GUI_Strings.Other or
             Text(Window.Log, i, 2) = GUI_Strings.Area  or
             Text(Window.Log, i, 2) = GUI_Strings.Program)
      then
        Insert_Item;
      end if;
    end Filter_by_Type;
  begin
    if to_boolean(State(Window.Alarm_Chk))
      and Text(Window.Log, i, 0) = GUI_Strings.Yes
    then
      Filter_by_Type(i);
    elsif not to_boolean(State(Window.Alarm_Chk)) then
      Filter_By_Type(i);
    end if;
  end Filter;

  procedure Create_Log_Window    (window : in out Log_Window_Type) is
  begin
    Create(Window.Window, "FFXI Alarm Log", width => 620, height => 300);
    Small_Icon (window.Window, Resources.Small_Icon);
    Large_Icon (window.Window, Resources.Large_Icon);
    Set_Font(Window.Window);

    Create(Window.Log, Window.Window, 5, 5,
           Client_Area_Width(Window.Window)-10,
           Client_Area_Height(Window.Window)-10,
           View => Report_View, Sort => Sort_Custom, Show => False);
    Insert_Column (Window.Log, "Alarm", 0, 45);
    Insert_Column (Window.Log, "Time", 1, 55);
    Insert_Column (Window.Log, "Type", 2, 70);
    Insert_Column (Window.Log, "Content", 3, 500);

    Create(Window.Filtered_Log, Window.Window, 5, 5,
           Client_Area_Width(Window.Window)-125,
           Client_Area_Height(Window.Window)-10,
           View => Report_View, Sort => Sort_Custom);
    Insert_Column (Window.Filtered_Log, "Alarm", 0, 45);
    Insert_Column (Window.Filtered_Log, "Time", 1, 55);
    Insert_Column (Window.Filtered_Log, "Type", 2, 70);
    Insert_Column (Window.Filtered_Log, "Content", 3, 500);

    Create(Window.Export, Window.Window, "Export",
           Client_Area_Width(Window.Window)-110-5,
           Client_Area_Height(Window.Window)-180-5,
           110, 25);

    Create(Window.Filter_Options, window.window,
           "Filters:",
           Client_Area_Width(Window.Window)-110-5,
           Client_Area_Height(Window.Window)-150-5,
           110, 150);
    Create_as_control (Window.Filter_Pan, Window.Filter_Options, "", 10, 17,
                       Client_Area_Width(Window.Filter_Options)-15,
                       Client_Area_Height(Window.Filter_Options)-20);
    Create (Window.Alarm_Chk, Window.Filter_Pan, "Only Alarms",    1, 0, 90, 20);
    State  (Window.Alarm_Chk, Unchecked);
    Create (Window.Tell_Chk,  Window.Filter_Pan, "Show Tells",     1, 18, 90, 20);
    State  (Window.Tell_Chk,  Checked);
    Create (Window.LS_Chk,    Window.Filter_Pan, "Show Linkshell", 1, 36, 90, 20);
    State  (Window.LS_Chk,    Checked);
    Create (Window.Party_Chk, Window.Filter_Pan, "Show Party",     1, 54, 90, 20);
    State  (Window.Party_Chk, Checked);
    Create (Window.Say_Chk,   Window.Filter_Pan, "Show Say",       1, 72, 90, 20);
    State  (Window.Say_Chk,   Checked);
    Create (Window.Shout_Chk, Window.Filter_Pan, "Show Shouts",    1, 90, 90, 20);
    State  (Window.Shout_Chk, Checked);
    Create (Window.Other_Chk, Window.Filter_Pan, "Show Others",    1, 108, 90, 20);
    State  (Window.Other_Chk, Checked);
  end Create_Log_Window;

  procedure Log_Event            (window  : in out Log_Window_Type;
                                  alarm   : in boolean;
                                  time    : in Ada.Calendar.Time;
                                  LType   : in Line_Type;
                                  content : in GWindows.GString) is
    pos : constant integer := Item_Count(Window.Log);
  begin
    if alarm then
      Insert_Item (Window.Log, GUI_Strings.Yes, pos);
    else
      Insert_Item (Window.Log, GUI_Strings.No, pos);
    end if;
    Set_Sub_Item (Window.Log, hour(time)&':'&minute(time)&':'&second(time),
                  pos, 1);
    case LType is
      when Area =>
        Set_Sub_Item (Window.Log, GUI_Strings.Area, pos, 2);
      when iTell | oTell =>
        Set_Sub_Item (Window.Log, GUI_Strings.Tell, pos, 2);
      when iLinkshell | oLinkshell =>
        Set_Sub_Item (Window.Log, GUI_Strings.Linkshell, pos, 2);
      when iParty | oParty =>
        Set_Sub_Item (Window.Log, GUI_Strings.Party, pos, 2);
      when iSay | oSay =>
        Set_Sub_Item (Window.Log, GUI_Strings.Say, pos, 2);
      when iShout | oShout=>
        Set_Sub_Item (Window.Log, GUI_Strings.Shout, pos, 2);
      when Program =>
        Set_Sub_Item (Window.Log, GUI_Strings.Program, pos, 2);
      when others =>
        Set_Sub_Item (Window.Log, GUI_Strings.Other, pos, 2);
    end case;
    Set_Sub_Item (Window.Log, content, pos, 3);
    Filter(Window, pos);
    if Get_Scroll_Pos(Window.Filtered_Log) = 100 then
      Scroll(Window.Filtered_Log, Bottom);
    end if;
  end Log_Event;

  procedure Filter               (Window : in out Log_Window_Type) is
    items : constant integer := Item_Count(Window.Log);
  begin
    Clear(Window.Filtered_Log);
    if Items > 0 then
      for i in 0..Item_Count(Window.Log)-1 loop
        Filter(Window, i);
      end loop;
    end if;
  end Filter;

  procedure Display_Log          (window : in out Log_Window_Type) is
  begin
    if not Visible (Window.Window) then
      Show(Window.Window);
    else
      Hide(Window.Window);
    end if;
  end Display_Log;

  procedure Resize_Log           (Window : in out Log_Window_Type) is
  begin
    Size(Window.Filtered_Log,
         abs (Client_Area_Width(Window.Window)-125),
         abs (Client_Area_Height(Window.Window)-10));
    Left(Window.Filter_Options,
         (Client_Area_Width(Window.Window)-110-5));
    Top (Window.Filter_Options,
         (Client_Area_Height(Window.Window)-150-5));
    Left(Window.Export,
         Client_Area_Width(Window.Window)-110-5);
    Top (Window.Export,
         Client_Area_Height(Window.Window)-180-5);
  end Resize_Log;

  procedure Export_Filtered (Window : in out Log_Window_Type) is
    use GWindows;
    use GWindows.Common_Dialogs;

    file_name : GString_Unbounded
      := GWindows.GStrings.To_GString_Unbounded(".\log.csv");
    file_title : GString_Unbounded;
    Done : Boolean;

    filter1 : constant filter_type :=
      (GWindows.GStrings.To_GString_Unbounded("Comma Separated Value (*.csv)"),
       GWindows.GStrings.To_GString_Unbounded("*.csv"));
    filter : filter_array(1..1);-- := (filter1);

    procedure Export_Filtered is
      f : export.file_type;
    begin
      export.Create(f, GWindows.GStrings.To_String(
             GWindows.GStrings.To_GString_From_Unbounded(file_name)));
      for i in 0..Item_Count(Window.Filtered_Log)-1 loop
        export.Add_Line(f,
          GWindows.GStrings.To_String(Text(Window.Filtered_Log, i, 1)),
          GWindows.GStrings.To_String(Text(Window.Filtered_Log, i, 2)),
          GWindows.GStrings.To_String(Text(Window.Filtered_Log, i, 3)));
      end loop;
      export.Close(f);
    end Export_Filtered;
  begin
    filter(1) := filter1;
    Save_File (Window.Window, "Export", file_name, filter, "csv", file_title, Done);
    if Done then
      Export_Filtered;
    end if;
  end Export_Filtered;

  procedure Close (Window : in out Log_Window_Type) is
  begin
    Close(Window.Window);
  end Close;
end GUI.Log;
